var OpenAjax = OpenAjax || {};
OpenAjax.a11y = OpenAjax.a11y || {};
OpenAjax.a11y.cache = OpenAjax.a11y.cache || {};

String.prototype.normalizeSpace = function() {
// Replace repeated spaces, newlines and tabs with a single space
return this.replace(/^\s*|\s(?=\s)|\s*$/g, "");
}

// DOM Node Type Constants

var NODE_TYPE = {};

NODE_TYPE.ELEMENT   = 1
NODE_TYPE.ATTRIBUTE = 2
NODE_TYPE.TEXT      = 3
NODE_TYPE.COMMENT   = 8
NODE_TYPE.DOCUMENT  = 9

// Link Object contains information about link on a web page
// OAA rules use this information to analyze
OpenAjax.a11y.cache.rule_result_object = function () {
  var rule_id = null;
  var message = "";
} // endif

// Link Object contains information about link on a web page
// OAA rules use this information to analyze
OpenAjax.a11y.cache.link_object = function () {
     var accessible_text  = "";
     var node_text        = "";
     var image_alt        = "";
     var image_only       = false;
     var href             = "";
     var order            = 0;
     var height           = 0;
     var width            = 0;
     var style_display    = "";
     var style_hidden     = "";
     var style_color      = "";
     var style_background_color = "";
     var node             = null;
     var rules_passed                    = [];  // Array of rule result objects
     var rules_violations                = [];  // Array of rule result objects
     var rules_recommendations           = [];  // Array of rule result objects
     var rules_potential_violations      = [];  // Array of rule result objects
     var rules_potential_recommendations = [];  // Array of rule result objects
} // end OpenAjax.a11y.cache.link_object


// ============================
// getAccessibleText
// 
// @node = Object  
// ============================
OpenAjax.a11y.cache.getAccessibleText = function( node ) {
  
  // Create return object
  var o = {};
  var strings = [];
  var alts = [];
  var texts = [];
  o.height = 0;
  o.width = 0;
  o.images = 0;
  getStrings( node, strings, texts, alts);  
  o.string = strings.join("");
  o.text   = texts.join("");
  o.alt    = alts.join("");
  return o;
  
    
  function getStrings( node, strings, tests, images) {
    // If text node get the text and return
    if( node.nodeType == NODE_TYPE.TEXT ) {
      var text = node.data;
      strings.push( text );
      texts.push( text );
    } else {
      // if an element for through all the children elements looking for text
      if( node.nodeType == NODE_TYPE.ELEMENT ) {
        // check to see if IMG or AREA element and to use ALT content if defined
        if((node.tagName == 'IMG') || (node.tagName == 'AREA')) {
          var alt = node.getAttribute('ALT');
          // check to make sure alt is defined
          if( alt ) {
            strings.push( alt );
            images.push( alt );
          } // endif
          
          if( node.offsetHeight > o.height ) {
             o.height = node.offsetHeight;
          } //endif
          
          if( node.offsetWidth > o.width ) {
             o.width = node.offsetWidth;
          } //endif
          
          o.images = o.images + 1;
          
        } else {
          for(var n = node.firstChild; n != null; n = n.nextSibling ) {
            getStrings( n, strings, tests, images);
          } // endfor
        } // endif  
      } // endif   
    } // endif
  } // end function getStrings
} // end function OpenAjax.cache.getAccessibleText

// ===================================
// 
//
// ===================================
 
OpenAjax.a11y.cache.updateLinkCache = function( doc ) {

  // Array of link objects
  OpenAjax.a11y.cache.links = [];

  for(var i=0; i < OpenAjax.a11y.cache.links.length; i++ ) {
    OpenAjax.a11y.cache.links.pop()
  }  // endfor
  
  var i=0;
  
  // get a array of A and AREA elements on the page
  getLinks( doc );
  
  return OpenAjax.a11y.cache.links;
  
  function getLinks( node ) {
    // if an element for through all the children elements looking for text
    if( node.nodeType == 1 ) {
      // check to see if A or AREA element and to use ALT content if defined
      if((node.tagName == 'A') || (node.tagName == 'AREA')) {
      
        if( node.href ) {
          
          var o = new OpenAjax.a11y.cache.link_object();
      
          var text_object = OpenAjax.a11y.cache.getAccessibleText(node);
    
          o.order            = i;
          o.accessible_text  = text_object.string.trim().normalizeSpace();
          o.compare_text     = text_object.string.trim().normalizeSpace().toLowerCase();
          o.node_text        = text_object.text.trim();
          o.image_alt        = text_object.alt.trim();
          o.image_only       = false;
          o.href             = node.href
          o.node             = node;

          o.height     = node.offsetHeight;
          o.width      = node.offsetWidth;

          // If the link is an image, use the image height and width
          if( o.height === 0 && o.width === 0 && text_object.height > 0 && text_object.width > 0 ) {
            o.height = text_object.height;
            o.width  = text_object.width;
            o.image_only = true;
          } // endif

          var style = getComputedStyle(node, null);
          
          o.style_display          = style.getPropertyValue("display");
          o.style_hidden           = style.getPropertyValue("hidden");
          o.style_color            = style.getPropertyValue("color");
          o.style_background_color = style.getPropertyValue("background-color");

          if( o.href ) {
            OpenAjax.a11y.cache.links[i] = o;
            i = i + 1;            
          } // endif
          
          // Rule results 
          o.rules_passed                    = [];  // Array of rule result objects
          o.rules_violations                = [];  // Array of rule result objects
          o.rules_recommendations           = [];  // Array of rule result objects
          o.rules_potential_violations      = [];  // Array of rule result objects
          o.rules_potential_recommendations = [];  // Array of rule result objects

        }  // endif 
      } // endif        
    } // endif
    
    for(var n = node.firstChild; n != null; n = n.nextSibling ) {
      getLinks( n );
    } // endfor
    
  } // end function getLinks
    
} // end function updateLinkCache


OpenAjax.a11y.cache.sortLinkCache = function( property , type) {  
 
  var swapped = false;
  var length = OpenAjax.a11y.cache.links.length;
  var temp = null;
  
  do {
     swapped = false;
     for( var i = 1; i < length; i++ ) {
       if(OpenAjax.a11y.cache.links[i-1][property] > OpenAjax.a11y.cache.links[i][property]) {
         // swap the values
         temp = OpenAjax.a11y.cache.links[i-1];
         OpenAjax.a11y.cache.links[i-1] = OpenAjax.a11y.cache.links[i];
         OpenAjax.a11y.cache.links[i] = temp;
         swapped = true;
       } // endif
     } // endfor  
  }  while (swapped);

} // end function sortLinkCache
